﻿using Sharp.WeShare.Common;
using Sharp.WeShare.MP.Card.Entity;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Newtonsoft;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Sharp.WeShare.MP.EnumKey;

namespace Sharp.WeShare.MP.Card
{
    public class CardApi
    {
        /// <summary>
        /// 上传卡券所用的图片
        /// 上传的图片限制文件大小限制1MB，仅支持JPG、PNG格式。
        /// </summary>
        /// <param name="accessToken"></param>
        /// <param name="filename"></param>
        /// <returns></returns>
        public static ImgUrl UploadImgUrl(string accessToken, string filename)
        {
            var url = string.Format("https://api.weixin.qq.com/cgi-bin/media/uploadimg?access_token={0}", accessToken);
            var form = new List<FormEntity>();
            form.Add(new FormEntity { IsFile = true, Name = "buffer", Value = filename });
            return Utils.UploadResult<ImgUrl>(url, form);
        }
        /// <summary>
        /// 获取卡券的颜色，默认是从缓存中获取的。由于卡券的颜色值很少变更，所以，为了提高效率，可缓存到内存中。
        /// </summary>
        /// <param name="accessToken">全局调用凭据</param>
        /// <param name="isfromCache">是否是从缓存中获取。</param>
        /// <returns></returns>
        public static CardColors GetColors(string accessToken, bool isfromCache = true)
        {
            string value = "";
            if (isfromCache)
            {
                value = CacheHelper.GetValue("cardcolors");
            }
            if (string.IsNullOrEmpty(value))
            {
                var url =
            string.Format("https://api.weixin.qq.com/card/getcolors?access_token={0}", accessToken);
                value = Utils.HttpGet(url);
                if (isfromCache)
                {
                    CacheHelper.Add("cardcolors", value, DateTime.Now.AddDays(30));
                }
            }
            return JsonConvert.DeserializeObject<CardColors>(value);

        }

        /// <summary>
        /// 创建卡券
        /// </summary>
        /// <param name="accessToken"></param>
        /// <param name="card"></param>
        /// <returns></returns>
        public static CardIdRes Create(string accessToken, BaseCard card)
        {
            var url = string.Format("https://api.weixin.qq.com/card/create?access_token={0}", accessToken);
            var data = new { card = card };
            return Utils.PostResult<CardIdRes>(data, url);
        }
        /// <summary>
        /// 设置买单接口.card_id已经设置了买单功能，不可变更为自助核销功能
        /// </summary>
        /// <param name="accessToken">全局调用凭据</param>
        /// <param name="cardId">卡券ID</param>
        /// <param name="isOpen">是否开启买单功能</param>
        /// <returns></returns>
        public static BaseRes SetPayCell(string accessToken, string cardId, bool isOpen)
        {
            var url = string.Format("https://api.weixin.qq.com/card/paycell/set?access_token={0}", accessToken);
            var data = new { card_id = cardId, is_open = isOpen };
            return Utils.PostResult<BaseRes>(data, url);
        }

        /// <summary>
        /// 设置自助核销.card_id已经设置了买单功能，不可变更为自助核销功能
        /// </summary>
        /// <param name="accessToken">全局调用凭据</param>
        /// <param name="cardId">卡券ID</param>
        /// <param name="isOpen">是否开启自助核销功能</param>
        /// <param name="needVerifyCode">是否需要输入验证码</param>
        /// <param name="needRemarkAmount">是否需要输入备注金额</param>
        /// <returns></returns>
        public static BaseRes SetSelfConsume(string accessToken, string cardId, bool isOpen, bool needVerifyCode = false, bool needRemarkAmount = false)
        {
            var url = string.Format("https://api.weixin.qq.com/card/selfconsumecell/set?access_token={0}", accessToken);
            var data = new { card_id = cardId, is_open = isOpen, need_verify_code = needVerifyCode, need_remark_amount = needRemarkAmount };
            return Utils.PostResult<BaseRes>(data, url);
        }
        /// <summary>
        /// 开通券点账户
        /// </summary>
        /// <param name="accessToken"></param>
        /// <returns></returns>
        public static Reward ActivateCoinAccount(string accessToken)
        {
            var url = string.Format("https://api.weixin.qq.com/card/pay/activate?access_token={0}", accessToken);
            return Utils.GetResult<Reward>(url);
            //p8mXIt6yBLyGtjQc7StNXhTE_2MI
        }
        /// <summary>
        /// 提前查询本次新增库存需要多少券点
        /// </summary>
        /// <param name="accessToken"></param>
        /// <param name="cardId">需要来配置库存的card_id</param>
        /// <param name="quantity">本次需要兑换的库存数目</param>
        /// <returns></returns>
        public static PayPrice GetPayPrice(string accessToken, string cardId, int quantity)
        {
            var url = string.Format("https://api.weixin.qq.com/card/pay/getpayprice?access_token={0}", accessToken);
            var data = new
            {
                card_id = cardId,
                quantity = quantity
            };
            return Utils.PostResult<PayPrice>(data, url);
        }
        /// <summary>
        /// 查询券点余额
        /// </summary>
        /// <param name="accessToken"></param>
        /// <returns></returns>
        public static CoinsInfo GetCoinsInfo(string accessToken)
        {
            var url = string.Format("https://api.weixin.qq.com/card/pay/getcoinsinfo?access_token={0}", accessToken);
            return Utils.GetResult<CoinsInfo>(url);
        }
        /// <summary>
        /// 确认兑换库存
        /// </summary>
        /// <param name="accessToken"></param>
        /// <param name="cardId">卡券id</param>
        /// <param name="orderId"></param>
        /// <param name="quantity"></param>
        /// <returns></returns>
        public static BaseRes ConfirmBuy(string accessToken, string cardId, string orderId, int quantity)
        {
            var url = string.Format("https://api.weixin.qq.com/card/pay/confirm?access_token={0}", accessToken);
            var data = new
            {
                card_id = cardId,
                quantity = quantity,
                order_id = orderId
            };
            return Utils.PostResult<BaseRes>(data, url);
        }
        /// <summary>
        /// 充值券点。开发者可以通过此接口为券点账户充值券点，1元等于1点。开发者调用接口后可以获得一个微信支付的支付二维码链接， 开发者可以将链接转化为二维码扫码支付。
        /// </summary>
        /// <param name="accessToken"></param>
        /// <param name="coinCount"></param>
        /// <returns></returns>
        public static RechargeQr Recharge(string accessToken, int coinCount)
        {
            var url = string.Format("https://api.weixin.qq.com/card/pay/recharge?access_token={0}", accessToken);
            var data = new { coin_count = coinCount };
            return Utils.PostResult<RechargeQr>(data, url);
        }
        /// <summary>
        /// 查询充值订单的状态
        /// </summary>
        /// <param name="accessToken">调用接口凭证</param>
        /// <param name="orderId"></param>
        /// <returns></returns>
        public static OrderInfo GetOrderInfo(string accessToken, string orderId)
        {
            var url = string.Format("https://api.weixin.qq.com/card/pay/getorder?access_token={0}", accessToken);
            var data = new { order_id = orderId };
            return Utils.PostResult<OrderInfo>(data, url);
        }

        public static OrderList GetOrderList(string accessToken, QueryOrderFilter filter)
        {
            var url = string.Format("https://api.weixin.qq.com/card/pay/getorderlist?access_token={0}", accessToken);
            var data = new
            {
                offset = filter.offset,
                count = filter.count,
                order_type = filter.order_type,
                nor_filter = new { status = filter.NorStatus },
                sort_info = new
                {
                    sort_key = filter.sort_key,
                    sort_type = filter.sort_type,
                },
                begin_time = Utils.ConvertDateTimeInt(filter.begin_time),
                end_time = Utils.ConvertDateTimeInt(filter.end_time)
            };
            return Utils.PostResult<OrderList>(data, url);
        }

        #region 投放
        /// <summary>
        /// 创建单卡券的二维码
        /// </summary>
        /// <param name="accessToken">调用凭据</param>
        /// <param name="expire">指定二维码的有效时间，范围是60 ~ 1800秒。不填默认为365天有效</param>
        /// <param name="param">卡券参数</param>
        /// <returns></returns>
        public static CardQrRes CreateQr(string accessToken, SingleCardParam param, int? expire = null)
        {
            var data = new
            {
                action_name = "QR_CARD",
                expire_seconds = expire,
                action_info = new
                {
                    card = param
                }
            };
            var url = string.Format("https://api.weixin.qq.com/card/qrcode/create?access_token={0}", accessToken);
            return Utils.PostResult<CardQrRes>(data, url);
        }

        /// <summary>
        /// 创建多卡券的二维码。领取多张的二维码一次最多填入5个card_id，否则报错
        /// </summary>
        /// <param name="accessToken">调用凭据</param>
        /// <param name="param">卡券参数</param>
        /// <returns></returns>
        public static CardQrRes CreateQr(string accessToken, MultipleCardParam param)
        {
            var data = new
            {
                action_name = "QR_MULTIPLE_CARD",
                action_info = new
                {
                    multiple_card = new
                    {
                        card_list = param
                    }
                }
            };
            var url = string.Format("https://api.weixin.qq.com/card/qrcode/create?access_token={0}", accessToken);
            return Utils.PostResult<CardQrRes>(data, url);
        }

        /// <summary>
        /// 创建卡券货架
        /// </summary>
        /// <param name="accessToken">全局调用凭据</param>
        /// <param name="page">货架参数</param>
        /// <returns></returns>
        public static LandingPageRes CreatePage(string accessToken, LandingPage page)
        {
            var url = string.Format("https://api.weixin.qq.com/card/landingpage/create?access_token={0}", accessToken);
            return Utils.PostResult<LandingPageRes>(page, url);
        }
        #endregion

        #region 自定义code
        /// <summary>
        /// 导入自定义code。
        /// 1）单次调用接口传入code的数量上限为100个。
        /// 2）每一个 code 均不能为空串。
        /// 3）导入结束后系统会自动判断提供方设置库存与实际导入code的量是否一致。
        /// 4）导入失败支持重复导入，提示成功为止。
        /// </summary>
        /// <param name="accessToken">全局调用凭据</param>
        /// <param name="cardId">卡券id</param>
        /// <param name="codes">自定义code列表</param>
        /// <returns></returns>
        public static ImportCodeRes ImportCode(string accessToken, string cardId, List<string> codes)
        {
            var url = string.Format("http://api.weixin.qq.com/card/code/deposit?access_token={0}", accessToken);
            var data = new { card_id = cardId, code = codes };
            return Utils.PostResult<ImportCodeRes>(data, url);
        }

        public static CheckCodeRes CheckCode(string accessToken, string cardId, List<string> codes)
        {
            var url = string.Format("http://api.weixin.qq.com/card/code/checkcode?access_token={0}", accessToken);
            var data = new { card_id = cardId, code = codes };
            return Utils.PostResult<CheckCodeRes>(data, url);
        }
        /// <summary>
        /// 查询导入成功的数量
        /// </summary>
        /// <param name="accessToken">全局调用凭据</param>
        /// <param name="cardId">卡券id</param>
        /// <returns></returns>
        public static CodeCount QueryCodeCount(string accessToken, string cardId)
        {
            var url = string.Format("http://api.weixin.qq.com/card/code/getdepositcount?access_token={0}", accessToken);
            var data = new { card_id = cardId };
            return Utils.PostResult<CodeCount>(data, url);
        }

        /// <summary>
        /// 生成可将卡券嵌入图文消息的html。
        /// </summary>
        /// <param name="accessToken">全局调用凭据</param>
        /// <param name="cardId">卡券id</param>
        /// <returns></returns>
        public static MpNewContent GetHtml(string accessToken, string cardId)
        {
            var url = string.Format("https://api.weixin.qq.com/card/mpnews/gethtml?access_token={0}", accessToken);
            var data = new { card_id = cardId };
            return Utils.PostResult<MpNewContent>(data, url);
        }
        #endregion

        /// <summary>
        /// 设置卡券测试白名单
        /// </summary>
        /// <param name="accessToken">全局调用凭据</param>
        /// <param name="openid">openid列表</param>
        /// <param name="username">微信号列表。与openid列表不能同时为空</param>
        /// <returns></returns>
        public static BaseRes SetTestWhiteList(string accessToken, List<string> openid = null, List<string> username = null)
        {
            var url = string.Format("https://api.weixin.qq.com/card/testwhitelist/set?access_token={0}", accessToken);
            var data = new { openid = openid, username = username };
            return Utils.PostResult<BaseRes>(data, url);
        }

        #region 核销
        /// <summary>
        /// 查询code
        /// </summary>
        /// <param name="accessToken">全局调用凭据</param>
        /// <param name="code"></param>
        /// <param name="checkConsume"></param>
        /// <param name="cardId"></param>
        /// <returns></returns>
        public static CodeInfoRes QueryCode(string accessToken, string code, bool? checkConsume = null, string cardId = null)
        {
            var url = string.Format("https://api.weixin.qq.com/card/code/get?access_token={0}", accessToken);
            var data = new
            {
                card_id = cardId,
                code = code,
                check_consume = true
            };
            return Utils.PostResult<CodeInfoRes>(data, url);
        }
        /// <summary>
        /// 核销卡券
        /// </summary>
        /// <param name="accessToken">全局调用凭据</param>
        /// <param name="code"></param>
        /// <param name="cardId">卡券ID。创建卡券时use_custom_code填写true时必填。非自定义Code不必填写。</param>
        /// <returns></returns>
        public static ConsumeRes Comsume(string accessToken, string code, string cardId = null)
        {
            var url = string.Format("https://api.weixin.qq.com/card/code/consume?access_token={0}", accessToken);
            var data = new
            {
                card_id = cardId,
                code = code
            };
            return Utils.PostResult<ConsumeRes>(data, url);
        }
        /// <summary>
        /// code解密。开发者若从url上获取到加密code,请注意先进行urldecode，否则报错。
        /// </summary>
        /// <param name="accessToken">全局调用凭据</param>
        /// <param name="encryptCode">经过加密的Code码。</param>
        /// <returns></returns>
        public static DecryptCodeRes DecryptCode(string accessToken, string encryptCode)
        {
            var url = string.Format("https://api.weixin.qq.com/card/code/decrypt?access_token={0}", accessToken);
            var data = new { encrypt_code = encryptCode };
            return Utils.PostResult<DecryptCodeRes>(data, url);
        }
        /// <summary>
        /// 获取用户所有的卡券列表
        /// </summary>
        /// <param name="accessToken">全局调用凭据</param>
        /// <param name="openId"></param>
        /// <param name="cardId"></param>
        /// <returns></returns>
        public static CardListByOpenIdRes GetCardListByOpenId(string accessToken, string openId, string cardId)
        {
            var url = string.Format("https://api.weixin.qq.com/card/user/getcardlist?access_token={0}", accessToken);
            var data = new { openid = openId, card_id = cardId };
            return Utils.PostResult<CardListByOpenIdRes>(data, url);
        }
        /// <summary>
        /// 获取卡券信息
        /// </summary>
        /// <param name="accessToken"></param>
        /// <param name="cardId"></param>
        /// <returns></returns>
        public static CardInfoRes GetCardInfo(string accessToken, string cardId)
        {
            var url = string.Format("https://api.weixin.qq.com/card/get?access_token={0}", accessToken);
            var data = new { card_id = cardId };
            JObject obj = Utils.PostResult<JObject>(data, url);
            CardInfoRes res = new CardInfoRes();
            res.errcode = obj.Value<int>("errcode");
            if (res.errcode == 0)
            {
                var type = obj["card"]["card_type"].Value<string>();
                var card = obj["card"];
                switch (type)
                {
                    case "DISCOUNT":
                        res.card = card.ToObject<Discount>(); break;
                    case "CASH":
                        res.card = card.ToObject<Cash>();
                        break;
                    case "GROUPON":
                        res.card = card.ToObject<Groupon>(); break;
                    case "GIFT":
                        res.card = card.ToObject<Gift>(); break;
                    case "GENERALCOUPON":
                        res.card = card.ToObject<GeneralCoupon>(); break;
                    case "MEMBER_CARD":
                    case "SCENIC_TICKET":
                    case "MOVIE_TICKET":
                    case "BOARDING_PASS":
                    case "BUS_TICKET":
                    case "MEETING_TICKET":
                    //res.card = card.ToObject<Mem>();break;
                    default:
                        break;
                }
            }
            else
            {
                res.errmsg = obj.Value<string>("errmsg");
            }
            return res;
        }
        /// <summary>
        /// 根据状态，查询卡券的列表
        /// </summary>
        /// <param name="accessToken"></param>
        /// <param name="offset">查询卡列表的起始偏移量，从0开始，即offset: 5是指从从列表里的第六个开始读取。</param>
        /// <param name="count">需要查询的卡片的数量（数量最大50）。</param>
        /// <param name="status"></param>
        /// <returns></returns>
        public static CardListByStatusRes QueryCardListByStatus(string accessToken, int offset, int count, List<CardStatus> status = null)
        {
            var url = string.Format("https://api.weixin.qq.com/card/batchget?access_token={0}", accessToken);
            var data = new { offset = offset, count = count, status_list = status };
            return Utils.PostResult<CardListByStatusRes>(data, url);
        }
        /// <summary>
        /// 更新卡券信息
        /// 1. 请开发者注意需要重新提审的字段，开发者调用更新接口时，若传入了提审字段则卡券需要重新进入审核状态；
        ///2. 接口更新方式为覆盖更新：即开发者只需传入需要更改的字段，其他字段无需填入，否则可能导致卡券重新提审；
        ///3. 若开发者置空某些字段，可直接在更新时传“”（空）；
        /// </summary>
        /// <param name="accessToken"></param>
        /// <param name="card"></param>
        /// <returns></returns>
        public static UpdateRes Update(string accessToken, BaseCard card)
        {
            var url = string.Format("https://api.weixin.qq.com/card/update?access_token={0}", accessToken);
            var data = new { card = card };
            return Utils.PostResult<UpdateRes>(data, url);
        }
        /// <summary>
        /// 修改库存
        /// </summary>
        /// <param name="accessToken"></param>
        /// <param name="cardId">卡券ID</param>
        /// <param name="value">要增加或者减少的库存数量。正数为增加</param>
        /// <returns></returns>
        public static BaseRes UpdateStock(string accessToken,string cardId,int value)
        {
            var url = string.Format("https://api.weixin.qq.com/card/modifystock?access_token={0}",accessToken);
            int increaseValue = 0;
            int reduceValue = 0;
            if (value>0)
            {
                increaseValue = value;
            }
            else
            {
                reduceValue = value * -1;
            }
            var data =new  { card_id =cardId, increase_stock_value = increaseValue, reduce_stock_value = reduceValue };
            return Utils.PostResult<BaseRes>(data, url);
        }
        #endregion

        #region 会员卡相关接口
        /// <summary>
        /// 会员卡激活
        /// </summary>
        /// <param name="accessToken"></param>
        /// <param name="param"></param>
        /// <returns></returns>
        public static BaseRes MemberCardActivate(string accessToken,ActivateParam param)
        {
            var url = string.Format("https://api.weixin.qq.com/card/membercard/activate?access_token={0}",accessToken);
            return Utils.PostResult<BaseRes>(param, url);
        }
        /// <summary>
        /// 设置激活字段
        /// </summary>
        /// <param name="accessToken"></param>
        /// <param name="param"></param>
        /// <returns></returns>
        public static BaseRes SetActivateForm(string accessToken, ActivateParam param)
        {
            var url = string.Format("https://api.weixin.qq.com/card/membercard/activateuserform/set?access_token={0}", accessToken);
            return Utils.PostResult<BaseRes>(param, url);
        }
        /// <summary>
        /// 跳转型一键激活，第三步，获取用户提交资料
        /// </summary>
        /// <param name="accessToken"></param>
        /// <param name="activateTicket"></param>
        /// <returns></returns>
        public static ActivateTempInfo GetActivateTempInfo(string accessToken, string activateTicket)
        {
            var url = string.Format("https://api.weixin.qq.com/card/membercard/activatetempinfo/get?access_token={0}",accessToken);
            var data = new { activate_ticket = activateTicket };
            return Utils.PostResult<ActivateTempInfo>(data, url);
        }
        /// <summary>
        /// 更新会员信息
        /// </summary>
        /// <param name="accessToken"></param>
        /// <param name="param"></param>
        /// <returns></returns>
        public static UpdateMemberRes UpdateMemberInfo(string accessToken,UpdateParam param)
        {
            var url = string.Format("https://api.weixin.qq.com/card/membercard/updateuser?access_token={0}", accessToken);
            return Utils.PostResult<UpdateMemberRes>(param, url);
        }
        #endregion
    }
}
